package dk.mirasola.systemtraining.bridgewidgets.client.ui.editor;


import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import dk.mirasola.systemtraining.bridgewidgets.shared.factory.ShapeElementFactory;
import dk.mirasola.systemtraining.bridgewidgets.shared.model.distributionfiltertree.shape.ShapeElement;

import java.util.ArrayList;
import java.util.List;


public abstract class ShapeElementsEditor extends Composite {
    interface ShapeElementsEditorUIBinder extends UiBinder<Widget, ShapeElementsEditor> {
    }

    private static ShapeElementsEditorUIBinder uiBinder = GWT.create(ShapeElementsEditorUIBinder.class);

    private List<ShapeElement> validated;

    @UiField
    TextBox patternEditor;
    @UiField
    Label help;
    @UiField(provided = true)
    HorizontalPanel panel;

    private KeyUpHandler keyUpHandler = new KeyUpHandler() {
        @Override
        public void onKeyUp(KeyUpEvent event) {
            String shapeStr = patternEditor.getText();
            String[] shapeElementStrings = shapeStr.split("-");
            if (shapeElementStrings.length != 4) {
                patternEditor.addStyleDependentName("invalid");
            } else {
                List<ShapeElement> shapeElements = new ArrayList<ShapeElement>();
                for (int j = 0; j < shapeElementStrings.length; j++) {
                    try {
                        shapeElements.add(ShapeElementFactory.stringToShapeElement(shapeElementStrings[j], true));
                    } catch (RuntimeException e) {
                        patternEditor.addStyleDependentName("invalid");
                        return;
                    }
                }

                if (isValid(shapeElements)) {
                    validated = shapeElements;
                    patternEditor.removeStyleDependentName("invalid");
                } else {
                    patternEditor.addStyleDependentName("invalid");
                }
            }
        }
    };


    private PopupPanel popupPanel;

    protected ShapeElementsEditor() {
        panel = new HorizontalPanel();
        panel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);

        initWidget(uiBinder.createAndBindUi(this));

        patternEditor.addKeyUpHandler(keyUpHandler);

        help.addMouseOverHandler(new MouseOverHandler() {
            @Override
            public void onMouseOver(MouseOverEvent event) {
                popupPanel = PopupFactory.createEditorInfoPopup(false, patternEditor.getAbsoluteLeft() + patternEditor.getOffsetHeight() + 10, patternEditor.getAbsoluteTop() + 20);
                popupPanel.setStylePrimaryName(ShapeElementsEditor.this.getStylePrimaryName() + "-help");
                popupPanel.setWidget(new HTML(getHelpInfo()));
                popupPanel.showRelativeTo(help);
                ;
            }
        });

        help.addMouseOutHandler(new MouseOutHandler() {
            @Override
            public void onMouseOut(MouseOutEvent event) {
                if (popupPanel != null) {
                    popupPanel.hide();
                    popupPanel = null;
                }
            }
        });
    }

    private String elementsToString(List<ShapeElement> elements) {
        StringBuilder builder = new StringBuilder();
        for (ShapeElement element : elements) {
            builder.append(ShapeElementFactory.shapeElementToString(element));
            builder.append("-");
        }
        builder.deleteCharAt(builder.length() - 1);
        return builder.toString();
    }

    protected List<ShapeElement> getValidatedShapeElements() {
        return validated;
    }

    protected void setValidatedShapeElement(List<ShapeElement> shapeElements) {
        this.validated = new ArrayList<ShapeElement>(shapeElements);
        patternEditor.setText(elementsToString(shapeElements));
    }

    protected abstract boolean isValid(List<ShapeElement> shapeElements);

    protected abstract SafeHtml getHelpInfo();
}
